#!/usr/bin/env python
# encoding: utf-8
"""
命令模式
讲一个请求封装为一个对象, 从而使你可用不同的请求对客户进行参数化
对请求排队或记录请求日志, 以及支持可撤销操作
- 比较容易设计一个命令队列
- 在需要情况下, 可以将命令计入日志
- 允许接受请求的一方决定是否要否决请求
- 可以容易的实现对请求的撤销和崇左
- 由于加紧新的具体命令类不影响其他类,  可以很容易新增
- 把请求一个操作的对象与指导怎么执行一个操作的对象分隔开
http://c.biancheng.net/view/1380.html
"""

from abc import ABCMeta, abstractmethod


class Command(metaclass=ABCMeta):
    """
    抽象命令类（Command）角色：声明执行命令的接口，拥有执行命令的抽象方法 execute()
    """

    def __init__(self, receiver):
        self.receiver = receiver

    @abstractmethod
    def execute(self):
        pass


class ConcreteCommand(Command):
    """
    具体命令类（Concrete Command）角色：是抽象命令类的具体实现类，它拥有接收者对象，并通过调用接收者的功能来完成命令要执行的操作。
    """

    def execute(self):
        self.receiver.action()

class HelpCommand(Command):

    def execute(self):
        self.receiver.help()


class RenameFile(Command):
    def __init__(self, path_src, path_dest, receiver):
        super().__init__(receiver)
        self.src, self.dest = path_src, path_dest


class Invoker(object):
    """
    调用者/请求者（Invoker）角色：是请求的发送者，它通常拥有很多的命令对象，并通过访问命令对象来执行相关请求，它不直接访问接收者。
    """

    def __init__(self):
        self.__commands = []

    @property
    def command(self):
        return self.__command

    @command.setter
    def command(self, value):
        self.__command = value

    def commands(self, cmd):
        self.__commands.append(cmd)

    def execute_command(self):
        self.__command.execute()

    def excute_commands(self):
        [cmd.execute() for cmd in self.__commands]


class Receiver(object):
    """
    实现者/接收者（Receiver）角色：执行命令功能的相关操作，是具体命令对象业务的真正实现者。
    """
    def action(self):
        print("execute command")

    def help(self):
        print("This is help display！！！")


if __name__ == '__main__':
    r = Receiver()

    cmd1 = ConcreteCommand(r)
    cmd2 = HelpCommand(r)

    invoker = Invoker()
    # invoker.command = cmd
    # invoker.execute_command()
    invoker.commands(cmd1)
    invoker.commands(cmd2)
    invoker.excute_commands()
